package org.github.manx98.jlibhac.tools.fssystem;

import org.github.manx98.jlibhac.common.Validity;
import org.github.manx98.jlibhac.fs.IStorage;
import org.github.manx98.jlibhac.util.BitUtil;

import java.io.IOException;

import static java.lang.System.out;

/**
 * @author Manx98
 * @version 1.0
 * @since 2022/10/4 0:45
 */
public class HierarchicalIntegrityVerificationStorage extends IStorage {
    private final IStorage[] levels;
    private final IntegrityCheckLevel integrityCheckLevel;
    private final Validity[][] levelValidities;
    private final IntegrityVerificationStorage[] integrityStorages;
    private final IStorage dataLevel;
    private final long length;
    private final boolean leaveOpen;

    public HierarchicalIntegrityVerificationStorage(IntegrityVerificationInfo[] levelInfo, IntegrityCheckLevel integrityCheckLevel, boolean leaveOpen) {
        super(0);
        this.levels = new IStorage[levelInfo.length];
        this.integrityCheckLevel = integrityCheckLevel;
        this.levelValidities = new Validity[levelInfo.length - 1][];
        this.integrityStorages = new IntegrityVerificationStorage[levelInfo.length - 1];

        this.levels[0] = levelInfo[0].data;

        for (int i = 1; i < levels.length; i++) {
            var levelData = new IntegrityVerificationStorage(levelInfo[i], levels[i - 1], integrityCheckLevel, leaveOpen);
            long levelSize = levelData.getSize();

            int cacheCount = Math.min((int) BitUtil.divideUp(levelSize, levelInfo[i].blockSize), 4);

            levels[i] = new CachedStorage(levelData, cacheCount, leaveOpen);
            levelValidities[i - 1] = levelData.getBlockValidities();
            integrityStorages[i - 1] = levelData;
        }

        this.dataLevel = levels[levels.length - 1];
        long dataSize = dataLevel.getSize();
        this.length = dataSize;
        this.leaveOpen = leaveOpen;
    }

    @Override
    public void read(long offset, byte[] destination, int destOffset, int len) throws IOException {
        this.dataLevel.read(offset, destination, destOffset, len);
    }

    @Override
    public long getSize() {
        return length;
    }
}
